大数乘法(一)

10 篇文章 0 订阅

            常用的大数相乘算法有模拟加减法和分治法,第一种符合我们的运算习惯,第二种用数学方法提高了效率,(具体描述与实现可参考http://www.cnblogs.com/heyonggang/p/3599857.html)而两种各有优势的方法的程序实现都比较复杂,并且不易于初学者理解,于是我琢磨出了一个将它们合二为一的方法,将权值与数组下标对应,而且其原理通俗易懂,所编程序也较简单。

       首先,通过一个例子来展示我们所运用的运算规律:

12*45=540;

12=1*10^1+2*10^0;------------------------把12每一位分解开

45=4*10^1+5*10^0;------------------------把45每一位分解开

12*45=(1*10^1+2*10^0)*(4*10^1+5*10^0)--------多项式相乘

             =1*4*10^(1+1)+1*5*10^(1+0)--------------可知n位数乘m位数需进行n*m次乘法

                                    +2*4*10^(0+1)+2*5*10^(0+0)-----和(n-1)*(m-1)次加法

             =4*10^2          +13*10^1        +10*10^0-------每一项其指数都是原来相乘的项的指数和 

             =540----------------而且积的位数为n+m(最高位有进位)或n+m-1(最高位无进位);

观察上面算式得出算法:

输入两个大数,并且将它们逆序保存在数组a与b中:

  大数a[n]={a[0],a[1],...,a[n]},大数b[m]={b[0],b[1],b[2],...,b[m]};

  声明保存结果的数组c[n+m];并且将元素初始化全为0;

其中,每一位的指数即是其下标,而分解相乘后的每一项值与指数分别为a[i]*b[j]和i+j;

a[i]*b[j]保存在c中以i+j为下标的的位置,仍然以上例来做演示,到这一步时c中元素为

101340
,


只需将其按照十进制进位规则进位即可,

0450
此时,将c去掉第一个大于0的数字前的0并倒序输出即为最终结果。

下面贴上c/c++代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<sstream>
#include <cstdlib>
using namespace std;

void assignment(int* s,int n){
	for(int i=0;i<n;i++){
		s[i]=0;
	}
} 
void Multiplication(char *arr1,char* arr2,int* Result){
	int n,m;n=strlen(arr1);m=strlen(arr2);
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			Result[i+j]=Result[i+j]+(arr1[i]-'0')*(arr2[j]-'0');
		}
	}
}
void reorganize(int *Result,int n){
	int t;
	for(int i=0;i<n;i++){
		if(Result[i]>9){
			t=Result[i]%10;
			Result[i+1]=Result[i+1]+Result[i]/10;
			Result[i]=t; 
		}
	}
}
int main(){
	string s1,s2;
	int n,m;char h;
	cin>>s1>>s2;
	n=s1.length();m=s2.length();
	char *arr1=new char[n];char *arr2=new char[m];
	int  *Result=new int[n+m]; 
	assignment(Result,n+m);
	int i=0,j=0;
	stringstream ss1(s1);while(ss1>>h)arr1[i++]=h;arr1[i]='\0';
	stringstream ss2(s2);while(ss2>>h)arr2[j++]=h;arr2[j]='\0';
	arr1=strrev(arr1);arr2=strrev(arr2);
	Multiplication(arr1,arr2,Result);
	reorganize(Result,n+m);
	int k,z=0;k=n+m;
	while(k--){
		if(Result[0]!=0||Result[k+1]==0&&Result[k]!=0){
			z=1;
		}
		if(z==1)printf("%d",Result[k]);
	}	
} 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闲敲代码、落灯花

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值